package adcon.persistencia;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 *
 * @author Diego
 */
public class DAO {

    private EntityManager em;
    private static EntityManagerFactory emf;


    static {
        emf = Persistence.createEntityManagerFactory("default");
    }

    public DAO() {
        this.em = emf.createEntityManager();
    }

    public void refrescar(Object objeto) {
        beginTransaction();
        em.refresh(objeto);
        commit();
        close();
    }

    public <T> T salvar(T o) {
        beginTransaction();
        T objetoRetorno = em.merge(o);
        commit();
        close();
        return objetoRetorno;
    }

    public void remover(Object o) {
        if (o instanceof Removivel) {
            Removivel objetoRemovivel = (Removivel) o;
            if (objetoRemovivel.isRemovido()) {
                throw new PersistenciaException("O objeto já foi removido!");
            }
            objetoRemovivel.setRemovido(true);
            salvar(o);
        } else {
            beginTransaction();
            o = em.merge(o);
            em.remove(o);
            commit();
            close();
        }
    }

    public void remover(List objetos) {
        for (Object objeto : objetos) {
            remover(objeto);
        }
    }

    public <T> List<T> listar(Class<T> classe) {
        Query q;
        if (ReflexaoUtil.implementa(classe, Removivel.class)) {
            q = em.createQuery("SELECT o FROM " + classe.getSimpleName() + " o WHERE o.removido = false");
        } else {
            q = em.createQuery("SELECT o FROM " + classe.getSimpleName() + " o");
        }
        q.setHint("toplink.refresh", "true");
        return q.getResultList();
    }

    public <T> List<T> listar(Class<T> classe, String nomeQuery, Object... args) {
        Query q = getNamedQuery(nomeQuery, args);
        return q.getResultList();
    }

    public <T> T localizar(Class<T> classe, long id) {
        T o = (T) em.find(classe, id);
        if (o != null) {
            em.refresh(o);
        }
        return o;
    }

    public <T> T localizar(Class classe, String nomeQuery, Object... args) {
        List<T> objetos = getNamedQuery(nomeQuery, args).getResultList();
        if (objetos.size() > 0) {
            return objetos.iterator().next();
        } else {
            return null;
        }
    }

    private Query getNamedQuery(String nomeQuery, Object... args) {
        Query query = em.createNamedQuery(nomeQuery);
        query.setHint("toplink.refresh", "true");
        try {
            for (int i = 1; i <= args.length; i++) {
                query.setParameter(i, args[i - 1]);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return query;
    }

    private void beginTransaction() {
        em.getTransaction().begin();
    }

    private void close() {
        em.close();
    }

    private void commit() {
        em.getTransaction().commit();
    }
}
